package com.adtech.export.util;

import java.beans.PropertyDescriptor;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.log4j.Logger;

/**
 * 从对象中获得指定属性值
 * 
 * @author liulm
 * 
 */
public class PropertyValueUtil {
	private static Logger logger = Logger.getLogger(PropertyValueUtil.class);

	// 日期格式化缓存
	private static Map<String, DateFormat> dateFormatMap = new HashMap<String, DateFormat>();
	// 数字格式化缓存
	private static Map<String, NumberFormat> numberFormatMap = new HashMap<String, NumberFormat>();

	/**
	 * 取出对象obj中根据fieldName指定的字段值。
	 * 
	 * <pre>
	 * 例子：user.getAddr().getDesc();等于getValue(user,"addr.desc");
	 * 		user.getAddrMap().get("desc");等于getValue(user,"addr.desc");
	 * </pre>
	 * 
	 * @param obj
	 *            要取得字段的对象。
	 * @param fieldName
	 *            以'.'分割的字段名字符串。
	 * 
	 * @return 返回指定字段值。当指定字段值，
	 * 
	 * @throws 当参数fieldName为null或空值时
	 *             ，抛出IllegalArgumentException异常。
	 */
	public static Object getValue(Object obj, String fieldName) {
		if (fieldName == null || fieldName.trim().length() == 0)
			throw new IllegalArgumentException("fieldName参数必须有值！");

		Object result = null;
		try {
			Class<?> clazz = PropertyUtils.getPropertyType(obj, fieldName);
			result  = PropertyConverterUtils.converter(clazz, 
					PropertyUtils.getProperty(obj, fieldName));
			
		} catch (Exception e) {
			logger.info("fieldName=" + fieldName, e);
		}
		return result;
	}

	/**
	 * 取出对象obj中根据fieldName指定的字段值。并根据formatPattern格式化为字符串。
	 * 
	 * @param obj
	 *            数据对象
	 * @param fieldName
	 *            访问字段
	 * @param formatPattern
	 *            格式化模式
	 *            参考java.text.SimpleDateFormat和java.text.DecimalFormat的模式设置。
	 * @param defaultValue
	 *            默认值
	 * @return 格式化后字符串。当格式化失败时，返回默认值。
	 */
	public static String getValueParseString(Object obj, String fieldName,
			String formatPattern, String defaultValue) {
		String result = null;
		Object valueObj = getValue(obj, fieldName);
		if (valueObj != null) {
			if (formatPattern != null && formatPattern.trim().length() > 0) {
				try {
					if (valueObj instanceof Date) {
						DateFormat dateFormat = getDateFormat(formatPattern);

						result = dateFormat.format(valueObj);
					} else if (valueObj instanceof Number) {
						NumberFormat numberFormat = getNumberFormat(formatPattern);
						result = numberFormat.format(valueObj);
					} else {
						result = String.valueOf(valueObj);
					}
				} catch (Exception e) {
					logger.error("fieldName=" + fieldName + "\tformatPattern="
							+ formatPattern, e);
				}

			} else {
				result = String.valueOf(valueObj);
			}
		}

		if (result == null)
			result = defaultValue;

		return result;
	}

	/**
	 * 获得数字格式化对象，如果缓存中有就取缓存的，否则重新创建一个并存入缓存
	 * 
	 * @param formatPattern
	 * @return
	 */
	private static NumberFormat getNumberFormat(String formatPattern) {
		NumberFormat numberFormat = numberFormatMap.get(formatPattern);
		if (numberFormat == null) {
			numberFormat = new DecimalFormat(formatPattern);
			numberFormatMap.put(formatPattern, numberFormat);
		}
		return numberFormat;
	}

	/**
	 * 获得日期格式化对象，如果缓存中有就取缓存的，否则重新创建一个并存入缓存
	 * 
	 * @param formatPattern
	 * @return
	 */
	private static DateFormat getDateFormat(String formatPattern) {
		DateFormat dateFormat = dateFormatMap.get(formatPattern);
		if (dateFormat == null) {
			dateFormat = new SimpleDateFormat(formatPattern);
			dateFormatMap.put(formatPattern, dateFormat);
		}
		return dateFormat;
	}

	/**
	 * 计算字符串的字符数，中文为2个字符。
	 * 
	 * @param str
	 * @return 以字符为单位的长度
	 */
	public static int getStringLengthForChar(String str) {
		int result = 0;
		if (str != null) {
			try {
				String charString = new String(str.getBytes(), ISO_8859_1);
				result = charString.length();
			} catch (Exception e) {
				e.printStackTrace();
				result = str.length();
			}
		}
		return result;

	}

	public final static String ISO_8859_1 = "iso_8859_1";
}
